// Copyright 2022 Huawei Cloud Computing Technology Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import Util from './Util';
import {DEVICE_ORIENTATION_ANGLES, CLOUD_PHONE_RATIO} from './config/commonConfig';
import PROTOCOL_CONFIG from './config/protocolConfig';

const ORIENTATION_DEGRESS = {
    'PORTRAIT': 0,
    'LANDSCAPE': 90,
    'REVERSE_LANDSCAPE': -90,
    'REVERSE_PORTRAIT': 180
};
const FULLSCREEN_CHANGE = ['webkitfullscreenchange', 'mozfullscreenchange', 'fullscreenchange', 'msFullscreenChange'];

export default class AutoRotation {
    constructor(videoContainerId, orientation, isMobile, callbackAfterRotate) {
        this.viewportOrientation = window.orientation || 0;
        this.orientation = orientation;
        this.videoContainerId = videoContainerId;
        this.videoContainer = document.getElementById(videoContainerId);
        this.originStyle = this.videoContainer && this.videoContainer.cssText || '';
        this.callbackAfterRotate = callbackAfterRotate;
        this.util = new Util();
        this.resizeTimer = null;
        this.isMobile = isMobile;
    }

    resize() {
        this.viewportOrientation = window.orientation || 0;
        this.rotatePlayer();
    }

    init() {
        if (!this.isMobile) {
            return;
        }
        // 若监听orientationChange事件，真机旋转后，需延时才能获取到真机旋转后屏幕宽高；监听resize事件，可立即获取旋转后的宽高。
        this.util.bind(window, 'resize', this.resize.bind(this));
        this.util.bind(window, 'orientationchange', this.resize.bind(this));
        FULLSCREEN_CHANGE.forEach(evt => {
            this.util.bind(document, evt, () => {
                setTimeout(() => {
                    this.rotatePlayer();
                }, 300);
            });
        });
    }

    updateOrientation(orientation, displayBox, directionHandler) {
        this.orientation = orientation;
        this.directionHandler = directionHandler;
        this.displayBox = displayBox;
        this.rotatePlayer();
    }

    rotatePlayer() {
        window.scrollTo(0, 0);
        let width = document.documentElement.clientWidth;
        let height = document.documentElement.clientHeight;
        const container = this.videoContainer || document.getElementById(this.videoContainerId);
        if (!container) {
            return;
        }

        const rect = container.parentNode && container.parentNode.getClientRects()[0];
        let style = '';
        let rotateDegrees = 0;
        let playerWidth = 0;
        let playerHeight = 0;
        if (rect) {
            if (this.isMobile) {
                const deviceOrientation = this.getDeviceOrientation();
                if ([DEVICE_ORIENTATION_ANGLES.PORTRAIT,DEVICE_ORIENTATION_ANGLES.REVERSE_PORTRAIT].includes(deviceOrientation)) {
                    if (this.orientation === PROTOCOL_CONFIG.ORIENTATION[0]) {
                        style = `
                            -webkit-transform: none;
                            -moz-transform: none;
                            -ms-transform: none;
                            transform: none;
                            width: ${width}px;
                            height: ${height}px;
                            position: relative;
                            top: 0px;
                            left: 0px;
                        `;
                    } else if (this.orientation === PROTOCOL_CONFIG.ORIENTATION[16]) {
                        rotateDegrees = ORIENTATION_DEGRESS[this.orientation];
                        style = `
                            -webkit-transform: rotate(${rotateDegrees}deg);
                            -moz-transform: rotate(${rotateDegrees}deg);
                            -ms-transform: rotate(${rotateDegrees}deg);
                            transform: rotate(${rotateDegrees}deg);
                            width: ${width}px;
                            height: ${height}px;
                            position: relative;
                            top: 0px;
                            left: 0px;
                        `;
                    } else if (this.orientation === PROTOCOL_CONFIG.ORIENTATION[8]) {
                        playerWidth = width;
                        playerHeight = playerWidth * CLOUD_PHONE_RATIO;
                        rotateDegrees = ORIENTATION_DEGRESS[this.orientation];
                        style = `
                            -webkit-transform: rotate(${rotateDegrees}deg);
                            -moz-transform: rotate(${rotateDegrees}deg);
                            -ms-transform: rotate(${rotateDegrees}deg);
                            transform: rotate(${rotateDegrees}deg);
                            -webkit-transform-origin: left;
                            -moz-transform-origin: left;
                            -ms-transform-origin: left;
                            transform-origin: left;
                            width: ${playerHeight}px;
                            height: ${playerWidth}px;
                            position: relative;
                            top: ${(height - playerHeight)/2}px;
                            left: ${playerWidth/2}px;
                        `;
                    } else if (this.orientation === PROTOCOL_CONFIG.ORIENTATION[24]) {
                        playerWidth = width;
                        playerHeight = playerWidth * CLOUD_PHONE_RATIO;
                        rotateDegrees = ORIENTATION_DEGRESS[this.orientation];
                        style = `
                            -webkit-transform: rotate(${rotateDegrees}deg);
                            -moz-transform: rotate(${rotateDegrees}deg);
                            -ms-transform: rotate(${rotateDegrees}deg);
                            transform: rotate(${rotateDegrees}deg);
                            -webkit-transform-origin: top;
                            -moz-transform-origin: top;
                            -ms-transform-origin: top;
                            transform-origin: top;
                            width: ${playerHeight}px;
                            height: ${playerWidth}px;
                            position: relative;
                            top: ${(height - playerHeight)/2 + playerHeight/2}px;
                            left: ${playerWidth - playerHeight/2}px;
                        `;
                    }
                } else if([DEVICE_ORIENTATION_ANGLES.LANDSCAPE, DEVICE_ORIENTATION_ANGLES.REVERSE_LANDSCAPE].includes(deviceOrientation)) {
                    if (this.orientation === PROTOCOL_CONFIG.ORIENTATION[0]) {
                        playerWidth = height * CLOUD_PHONE_RATIO;
                        playerHeight = height;
                        style = `
                            -webkit-transform: none;
                            -moz-transform: none;
                            -ms-transform: none;
                            transform: none;
                            width: ${playerWidth}px;
                            height: ${playerHeight}px;
                            position: relative;
                            top: 0px;
                            left: ${(width - playerWidth)/2}px;
                        `;
                    } else if (this.orientation === PROTOCOL_CONFIG.ORIENTATION[16]) {
                        playerWidth = height * CLOUD_PHONE_RATIO;
                        playerHeight = height;
                        rotateDegrees = ORIENTATION_DEGRESS[this.orientation];
                        style = `
                            -webkit-transform: rotate(${rotateDegrees}deg);
                            -moz-transform: rotate(${rotateDegrees}deg);
                            -ms-transform: rotate(${rotateDegrees}deg);
                            transform: rotate(${rotateDegrees}deg);
                            width: ${playerWidth}px;
                            height: ${playerHeight}px;
                            position: relative;
                            top: 0px;
                            left: ${(width - playerWidth)/2}px;
                        `;
                    } else if (this.orientation === PROTOCOL_CONFIG.ORIENTATION[8]) {
                        rotateDegrees = ORIENTATION_DEGRESS[this.orientation];
                        style = `
                            -webkit-transform: rotate(${rotateDegrees}deg);
                            -moz-transform: rotate(${rotateDegrees}deg);
                            -ms-transform: rotate(${rotateDegrees}deg);
                            transform: rotate(${rotateDegrees}deg);
                            -webkit-transform-origin: left;
                            -moz-transform-origin: left;
                            -ms-transform-origin: left;
                            transform-origin: left;
                            width: ${height}px;
                            height: ${width}px;
                            position: relative;
                            top: ${height - width/2}px;
                            left: ${width/2}px;
                        `;
                    } else if (this.orientation === PROTOCOL_CONFIG.ORIENTATION[24]) {
                        rotateDegrees = ORIENTATION_DEGRESS[this.orientation];
                        style = `
                            -webkit-transform: rotate(${rotateDegrees}deg);
                            -moz-transform: rotate(${rotateDegrees}deg);
                            -ms-transform: rotate(${rotateDegrees}deg);
                            transform: rotate(${rotateDegrees}deg);
                            -webkit-transform-origin: top;
                            -moz-transform-origin: top;
                            -ms-transform-origin: top;
                            transform-origin: top;
                            width: ${height}px;
                            height: ${width}px;
                            position: relative;
                            top: ${height/2}px;
                            left: ${width - height/2}px;
                        `;
                    }
                }
            } else {
                width = Math.max(width - Math.max(rect.left * 2, 0), 0);
                height = Math.min(height - Math.max(rect.top * 2, 0), rect.height);
                
                // 根据本地视口方向和云手机方向判断播放器dom的旋转方向，将播放器旋转至视口方向。顺时针为正数，逆时针为负数
                if (this.orientation === 'PORTRAIT') {
                    style = `
                        -webkit-transform: none;
                        -moz-transform: none;
                        -ms-transform: none;
                        transform: none;
                        width: ${width}px;
                        height: ${height}px;
                        position: relative;
                        top: 0px;
                        left: 0px;
                    `;
                } else if (this.orientation === 'REVERSE_PORTRAIT') {
                    rotateDegrees = ORIENTATION_DEGRESS[this.orientation];
                    style = `
                        -webkit-transform: rotate(${rotateDegrees}deg);
                        -moz-transform: rotate(${rotateDegrees}deg);
                        -ms-transform: rotate(${rotateDegrees}deg);
                        transform: rotate(${rotateDegrees}deg);
                        -webkit-transform-origin: '50% 50%';
                        -moz-transform-origin: '50% 50%';
                        -ms-transform-origin: '50% 50%';
                        transform-origin: '50% 50%';
                        width: ${width}px;
                        height: ${height}px;
                        position: relative;
                        top: 0px;
                        left: 0px;
                    `;
                } else {
                    // 云手机横屏时顺时针旋转，竖屏时逆时针旋转
                    rotateDegrees = ORIENTATION_DEGRESS[this.orientation];
                    style = `
                        -webkit-transform: rotate(${rotateDegrees}deg);
                        -moz-transform: rotate(${rotateDegrees}deg);
                        -ms-transform: rotate(${rotateDegrees}deg);
                        transform: rotate(${rotateDegrees}deg);
                        -webkit-transform-origin: '50% 50%';
                        -moz-transform-origin: '50% 50%';
                        -ms-transform-origin: '50% 50%';
                        transform-origin: '50% 50%';
                        width: ${height}px;
                        height: ${width}px;
                        position: relative;
                        top: ${(height - width) / 2}px;
                        left: ${0 - (height - width) / 2}px;
                    `;
                }
            }
        }

        container.style.cssText = this.originStyle + style;

        // 旋转后通过getClientRects()立即获取宽高可能会获取到旋转前的宽高
        this.callbackAfterRotate && setTimeout(() => {
            this.callbackAfterRotate(rotateDegrees);
        }, 300);

        if (this.directionHandler) {
            const keyboardEle = document.getElementById('keyboardInputContent');
            const currentDisplay = keyboardEle?.style?.display;
            this.directionHandler.update(this.orientation, this.displayBox, currentDisplay);
        }
    }

    destroy() {
        const container = this.videoContainer || document.getElementById(this.videoContainerId);
        container && (container.style.cssText = this.originStyle);
        if (this.isMobile) {
            this.util.unbind(window, 'resize');
            this.util.unbind(window, 'orientationchange');
            FULLSCREEN_CHANGE.forEach(evt => {
                this.util.unbind(document, evt);
            });
        }
    }

    getDeviceOrientation() {
        return window?.screen?.orientation?.angle || window.orientation;
    }
}
